Micron Document
Deavmi's coding shack

Node / personal / ini / files / parse.go

Displaying Raw • Download

parse.go HEAD (c6487113) Text, 10.69 KB

Tff7b72package Te6edf3ini

Tff7b72import Tb4b4b4(
Ta5d6ff"errors"
Ta5d6ff"fmt"
Ta5d6ff"io"

Te6edf3gostrings Ta5d6ff"strings"

Te6edf3fflogger Ta5d6ff"new.git.deavmi.assigned.network/deavmi/freefaces.git/logging"
Te6edf3nulllogger Ta5d6ff"new.git.deavmi.assigned.network/deavmi/glog.git/null"
Ta5d6ff"new.git.deavmi.assigned.network/deavmi/go-niknaks.git/parse"
Ta5d6ff"new.git.deavmi.assigned.network/deavmi/go-niknaks.git/strings"
Ta5d6ff"new.git.deavmi.assigned.network/deavmi/go-niknaks.git/types"
Tb4b4b4)

T8b949e// an INI parser
Tff7b72type Te6edf3Parser Tff7b72struct Tb4b4b4{
T8b949e// cursor for reading tokens from
Te6edf3c Tff7b72*Te6edf3parseTb4b4b4.Te6edf3Cursor

T8b949e// Ini
Te6edf3ini Te6edf3Ini

T8b949e// stack of comments (TODO: Make into a stack)
Te6edf3cs_stk Tb4b4b4[Tb4b4b4]Tffa657string

T8b949e// sections
Te6edf3sc_ls Tb4b4b4[Tb4b4b4]Tff7b72*Te6edf3Section

T8b949e// logging
Te6edf3log Te6edf3ffloggerTb4b4b4.Te6edf3Logger
Tb4b4b4}

T8b949e// creates a new INI parser from the
T8b949e// provided reader.
Tff7b72func Te6edf3NewParserTb4b4b4(Te6edf3rs Te6edf3ioTb4b4b4.Te6edf3ReaderTb4b4b4) Tb4b4b4(Te6edf3ParserTb4b4b4, Tffa657errorTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3NewParserWithLoggerTb4b4b4(Te6edf3rsTb4b4b4, Te6edf3nullloggerTb4b4b4.Te6edf3NewOpaqueTb4b4b4(Ta5d6ff""Tb4b4b4)Tb4b4b4)
Tb4b4b4}

T8b949e// creates a new INI parser from the
T8b949e// provided reader.
T8b949e//
T8b949e// Also allows specifying the logger
T8b949e// to use. Note that the logging level
T8b949e// should be set to TRACE at the very
T8b949e// least, if you want to see anything
Tff7b72func Te6edf3NewParserWithLoggerTb4b4b4(Te6edf3rs Te6edf3ioTb4b4b4.Te6edf3ReaderTb4b4b4, Te6edf3logger Te6edf3ffloggerTb4b4b4.Te6edf3LoggerTb4b4b4) Tb4b4b4(Te6edf3ParserTb4b4b4, Tffa657errorTb4b4b4) Tb4b4b4{
Tff7b72if Te6edf3rs Tff7b72== Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Te6edf3ParserTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3fmtTb4b4b4.Te6edf3ErrorfTb4b4b4(Ta5d6ff"The rs cannot be nil"Tb4b4b4)
Tb4b4b4}

Tff7b72var Te6edf3p Te6edf3Parser Tff7b72= Te6edf3ParserTb4b4b4{Tb4b4b4}
Te6edf3pTb4b4b4.Te6edf3ini Tff7b72= Te6edf3newIniTb4b4b4(Tb4b4b4)

T8b949e// setup cursor
Tff7b72if Te6edf3cTb4b4b4, Te6edf3e Tff7b72:= Te6edf3parseTb4b4b4.Te6edf3NewTb4b4b4(Te6edf3rsTb4b4b4)Tb4b4b4; Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Te6edf3ParserTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3c Tff7b72= Tff7b72&Te6edf3c
Tb4b4b4}

T8b949e// setup logger
Te6edf3pTb4b4b4.Te6edf3log Tff7b72= Te6edf3logger

Tff7b72return Te6edf3pTb4b4b4, Tff7b72nil
Tb4b4b4}

T8b949e// parses the data from the reader into a new
T8b949e// Ini instance. The error is set if a problem
T8b949e// occurs during parsing either due to the
T8b949e// reader `rs` or the parsed data
Tff7b72func Tb4b4b4(Te6edf3p Tff7b72*Te6edf3ParserTb4b4b4) Te6edf3ParseTb4b4b4(Tb4b4b4) Tb4b4b4(Tff7b72*Te6edf3IniTb4b4b4, Tffa657errorTb4b4b4) Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3TraceTb4b4b4(Ta5d6ff"parse enter"Tb4b4b4)

Tff7b72for Tb4b4b4{
Te6edf3rTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3CurrentCharacterTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3errorsTb4b4b4.Te6edf3IsTb4b4b4(Te6edf3eTb4b4b4, Te6edf3ioTb4b4b4.Te6edf3EOFTb4b4b4) Tb4b4b4{ T8b949e// EOF is allowed here
Tff7b72break
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tff7b72*Te6edf3IniTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4}

Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3TraceTb4b4b4(Ta5d6ff"rune: %c"Tb4b4b4, Te6edf3rTb4b4b4)

Tff7b72if Te6edf3r Tff7b72== Ta5d6ff' ' Tff7b72|| Te6edf3r Tff7b72== Ta5d6ff'\t' Tff7b72|| Te6edf3r Tff7b72== Ta5d6ff'\n' Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tff7b72continue
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3r Tff7b72== Ta5d6ff';' Tb4b4b4{ T8b949e// parse a comment
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4) T8b949e// consume the `;`
Te6edf3cTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3parseCommentTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tff7b72*Te6edf3IniTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4}

Te6edf3pTb4b4b4.Te6edf3cs_stk Tff7b72= Tffa657appendTb4b4b4(Te6edf3pTb4b4b4.Te6edf3cs_stkTb4b4b4, Te6edf3cTb4b4b4)
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3r Tff7b72== Ta5d6ff'[' Tb4b4b4{ T8b949e// section beginning
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4) T8b949e// consume the `[`
Te6edf3sTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3parseSectionTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tff7b72*Te6edf3IniTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4}

Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3DebugTb4b4b4(Ta5d6ff"Section derived: %v"Tb4b4b4, Te6edf3sTb4b4b4)
Te6edf3sTb4b4b4.Te6edf3parent Tff7b72= Tff7b72&Te6edf3pTb4b4b4.Te6edf3ini T8b949e// parent
Tff7b72if Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3iniTb4b4b4.Te6edf3addSectionTb4b4b4(Tff7b72&Te6edf3sTb4b4b4)Tb4b4b4; Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tff7b72*Te6edf3IniTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3InfoTb4b4b4(Ta5d6ff"Done"Tb4b4b4)
Tff7b72return Tff7b72&Te6edf3pTb4b4b4.Te6edf3iniTb4b4b4, Tff7b72nil

Tb4b4b4}

T8b949e// parses a section
Tff7b72func Tb4b4b4(Te6edf3p Tff7b72*Te6edf3ParserTb4b4b4) Te6edf3parseSectionTb4b4b4(Tb4b4b4) Tb4b4b4(Te6edf3SectionTb4b4b4, Tffa657errorTb4b4b4) Tb4b4b4{
Tff7b72var Te6edf3sec Te6edf3Section

T8b949e// parse header (section name)
Te6edf3sectionNameTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3parseSection_headerTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Te6edf3SectionTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4}
Te6edf3secTb4b4b4.Te6edf3name Tff7b72= Te6edf3sectionName

T8b949e// keep parsing key-value pairs until we get the opening
T8b949e// character of the next section (i.e. a `[`)
Tff7b72for Tb4b4b4{
Te6edf3rTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3CurrentCharacterTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3errorsTb4b4b4.Te6edf3IsTb4b4b4(Te6edf3eTb4b4b4, Te6edf3ioTb4b4b4.Te6edf3EOFTb4b4b4) Tb4b4b4{ T8b949e// EOF is allowed here
Tff7b72break
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{ T8b949e// any other error is not allowed
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Te6edf3SectionTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4}

T8b949e// next section begins
Tff7b72if Te6edf3r Tff7b72== Ta5d6ff'[' Tb4b4b4{
T8b949e// do NOT consume `[` but rather leave
T8b949e// it for caller's state machine so it
T8b949e// knows to enter us again
Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3DebugTb4b4b4(Ta5d6ff"End of key-pairs for section '%s'"Tb4b4b4, Te6edf3sectionNameTb4b4b4)
Tff7b72break
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3r Tff7b72== Ta5d6ff' ' Tff7b72|| Te6edf3r Tff7b72== Ta5d6ff'\t' Tff7b72|| Te6edf3r Tff7b72== Ta5d6ff'\n' Tb4b4b4{ T8b949e// skip these
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tff7b72continue
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3r Tff7b72== Ta5d6ff';' Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4) T8b949e// consume the `;`
Te6edf3cTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3parseCommentTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Te6edf3SectionTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4}

Te6edf3pTb4b4b4.Te6edf3cs_stk Tff7b72= Tffa657appendTb4b4b4(Te6edf3pTb4b4b4.Te6edf3cs_stkTb4b4b4, Te6edf3cTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// parse a record (we provided &sec for parenting)
Te6edf3recTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3parseRecordTb4b4b4(Tff7b72&Te6edf3secTb4b4b4)
Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Te6edf3SectionTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4}

Te6edf3secTb4b4b4.Te6edf3AppendRecordTb4b4b4(Te6edf3recTb4b4b4) T8b949e// add record
Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3DebugTb4b4b4(Ta5d6ff"Got record: %v"Tb4b4b4, Te6edf3recTb4b4b4)
Tb4b4b4}
Tb4b4b4}

Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3DebugTb4b4b4(Ta5d6ff"e before leave: %v"Tb4b4b4, Te6edf3eTb4b4b4)
Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3TraceTb4b4b4(Ta5d6ff"Parsed section '%v'"Tb4b4b4, Te6edf3secTb4b4b4)
Tff7b72return Te6edf3secTb4b4b4, Tff7b72nil
Tb4b4b4}

T8b949e// checks if the key/value name is valod
Tff7b72func Te6edf3isValidKeyValueNameTb4b4b4(Te6edf3s Tffa657stringTb4b4b4) Tffa657bool Tb4b4b4{
Tff7b72if Tffa657lenTb4b4b4(Te6edf3sTb4b4b4) Tff7b72> T79c0ff0 Tff7b72&& Te6edf3stringsTb4b4b4.Te6edf3IsNumericTb4b4b4(Tffa657runeTb4b4b4(Te6edf3sTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72false
Tb4b4b4}

Tff7b72var Te6edf3strToCheck Tffa657string Tff7b72= Te6edf3s
Tff7b72if Te6edf3p Tff7b72:= Te6edf3gostringsTb4b4b4.Te6edf3IndexTb4b4b4(Te6edf3strToCheckTb4b4b4, Ta5d6ff"_"Tb4b4b4)Tb4b4b4; Te6edf3p Tff7b72!= Tff7b72-T79c0ff1 Tb4b4b4{
Te6edf3strToCheck Tff7b72= Te6edf3strToCheckTb4b4b4[Te6edf3pTff7b72+T79c0ff1Tb4b4b4:Tb4b4b4]
Tb4b4b4}

Tff7b72return Te6edf3stringsTb4b4b4.Te6edf3IsAlphaNumericStringTb4b4b4(Te6edf3strToCheckTb4b4b4)
Tb4b4b4}

T8b949e// parses a record and parents it into the
T8b949e// given section
Tff7b72func Tb4b4b4(Te6edf3p Tff7b72*Te6edf3ParserTb4b4b4) Te6edf3parseRecordTb4b4b4(Te6edf3sec Tff7b72*Te6edf3SectionTb4b4b4) Tb4b4b4(Te6edf3RecordTb4b4b4, Tffa657errorTb4b4b4) Tb4b4b4{
Tff7b72var Te6edf3keyBuild Tffa657string
Tff7b72var Te6edf3valueBuild Tffa657string

T8b949e// parse the key
Te6edf3n_sTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3parseBasicValueTb4b4b4(Ta5d6ff'='Tb4b4b4)
Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3DebugTb4b4b4(Ta5d6ff"n_s: %s"Tb4b4b4, Te6edf3n_sTb4b4b4)
Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Te6edf3RecordTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3isValidKeyValueNameTb4b4b4(Te6edf3n_sTb4b4b4) Tff7b72== Tff7b72false Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Te6edf3RecordTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3fmtTb4b4b4.Te6edf3ErrorfTb4b4b4(Ta5d6ff"Key '%s' can only contain numbers, letters and _ and may not start with a number"Tb4b4b4, Te6edf3n_sTb4b4b4)
Tb4b4b4}
Te6edf3keyBuild Tff7b72= Te6edf3n_s

T8b949e// parse the `=`
Te6edf3eqTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3parseRuneTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Te6edf3RecordTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3eq Tff7b72!= Ta5d6ff"=" Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Te6edf3RecordTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3fmtTb4b4b4.Te6edf3ErrorfTb4b4b4(Ta5d6ff"Expected `=` but got `%s`"Tb4b4b4, Te6edf3eqTb4b4b4)
Tb4b4b4}

T8b949e// parse the value
Te6edf3v_sTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3parseBasicValueTb4b4b4(Ta5d6ff'='Tb4b4b4)
Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Te6edf3RecordTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4} T8b949e//else if isValidKeyValueName(v_s) == false {
T8b949e// return types.Zero[Record](), fmt.Errorf("Value '%s' can only contain numbers, letters and _ and may not start with a number", v_s)
T8b949e// }
Te6edf3valueBuild Tff7b72= Te6edf3v_s

T8b949e// TODO: Add setting of comment IF present
Tff7b72var Te6edf3record Te6edf3Record Tff7b72= Te6edf3RecordTb4b4b4{Te6edf3nameTb4b4b4: Te6edf3keyBuildTb4b4b4, Te6edf3valueTb4b4b4: Te6edf3valueBuildTb4b4b4, Te6edf3parentTb4b4b4: Te6edf3secTb4b4b4}

Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3DebugTb4b4b4(Ta5d6ff"New record: %v"Tb4b4b4, Te6edf3recordTb4b4b4)

Tff7b72return Te6edf3recordTb4b4b4, Tff7b72nil
Tb4b4b4}

T8b949e// skips all whitespace too
Tff7b72func Tb4b4b4(Te6edf3p Tff7b72*Te6edf3ParserTb4b4b4) Te6edf3parseRuneTb4b4b4(Tb4b4b4) Tb4b4b4(Tffa657stringTb4b4b4, Tffa657errorTb4b4b4) Tb4b4b4{
Tff7b72var Te6edf3out_r Tffa657rune
Tff7b72var Te6edf3gotRune Tffa657bool Tff7b72= Tff7b72false
Tff7b72for Tb4b4b4{
Te6edf3rTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3CurrentCharacterTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
T8b949e// EOF here is allowed IF we have the rune already
Tff7b72if Te6edf3errorsTb4b4b4.Te6edf3IsTb4b4b4(Te6edf3eTb4b4b4, Te6edf3ioTb4b4b4.Te6edf3EOFTb4b4b4) Tff7b72&& Te6edf3gotRune Tb4b4b4{
Tff7b72break
Tb4b4b4}
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tffa657stringTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4}

Tff7b72if Te6edf3r Tff7b72== Ta5d6ff' ' Tff7b72|| Te6edf3r Tff7b72== Ta5d6ff'\t' Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tff7b72continue
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3out_r Tff7b72= Te6edf3r
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4) T8b949e// consume the rune
Te6edf3gotRune Tff7b72= Tff7b72true
Tff7b72break
Tb4b4b4}
Tb4b4b4}
Tff7b72return Tffa657stringTb4b4b4(Te6edf3out_rTb4b4b4)Tb4b4b4, Tff7b72nil
Tb4b4b4}

Tff7b72func Tb4b4b4(Te6edf3p Tff7b72*Te6edf3ParserTb4b4b4) Te6edf3parseEscapeSequenceTb4b4b4(Tb4b4b4) Tb4b4b4(Tffa657stringTb4b4b4, Tffa657errorTb4b4b4) Tb4b4b4{
T8b949e// upon entry consume the `\`
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)

Te6edf3rTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3CurrentCharacterTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tffa657stringTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3fmtTb4b4b4.Te6edf3ErrorfTb4b4b4(Ta5d6ff"Expecting next character for escape sequence but got error %v"Tb4b4b4, Te6edf3eTb4b4b4)
Tb4b4b4}

T8b949e// on exit consume the single escape
T8b949e// token
Tff7b72defer Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3r Tff7b72== Ta5d6ff'n' Tb4b4b4{
Tff7b72return Ta5d6ff"\n"Tb4b4b4, Tff7b72nil
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3r Tff7b72== Ta5d6ff't' Tb4b4b4{
Tff7b72return Ta5d6ff"\t"Tb4b4b4, Tff7b72nil
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3r Tff7b72== Ta5d6ff'"' Tb4b4b4{
Tff7b72return Ta5d6ff"\""Tb4b4b4, Tff7b72nil
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tffa657stringTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3fmtTb4b4b4.Te6edf3ErrorfTb4b4b4(Ta5d6ff"Escape sequence '\\%c' is not supported"Tb4b4b4, Te6edf3rTb4b4b4)
Tb4b4b4}
Tb4b4b4}

T8b949e// parses a string-enclosed value, stripping it of
T8b949e// its opening and closing `"` and also supporting
T8b949e// escape sequences
Tff7b72func Tb4b4b4(Te6edf3p Tff7b72*Te6edf3ParserTb4b4b4) Te6edf3parseStringEnclosedValueTb4b4b4(Tb4b4b4) Tb4b4b4(Tffa657stringTb4b4b4, Tffa657errorTb4b4b4) Tb4b4b4{
T8b949e// upon entry consume thee `"`
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)

Tff7b72var Te6edf3strBuildUp Tffa657string

Tff7b72for Tb4b4b4{
Te6edf3rTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3CurrentCharacterTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
T8b949e// EOF here is fine if we got some string
Tff7b72if Te6edf3errorsTb4b4b4.Te6edf3IsTb4b4b4(Te6edf3eTb4b4b4, Te6edf3ioTb4b4b4.Te6edf3EOFTb4b4b4) Tff7b72&& Tffa657lenTb4b4b4(Te6edf3strBuildUpTb4b4b4) Tff7b72> T79c0ff0 Tb4b4b4{
Tff7b72break
Tb4b4b4}
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tffa657stringTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4}

T8b949e// grab the escape sequence and transform
T8b949e// it into a string ("escape" it)
Tff7b72if Te6edf3r Tff7b72== Ta5d6ff'\\' Tb4b4b4{
Tff7b72if Te6edf3genStrTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3parseEscapeSequenceTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tffa657stringTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// tack on the string and move on
Te6edf3strBuildUp Tff7b72+= Te6edf3genStr
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3r Tff7b72== Ta5d6ff'"' Tb4b4b4{ T8b949e// exit
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tff7b72break
Tb4b4b4} Tff7b72else Tb4b4b4{ T8b949e// build up
Te6edf3strBuildUp Tff7b72+= Tffa657stringTb4b4b4(Te6edf3rTb4b4b4)
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tff7b72return Te6edf3strBuildUpTb4b4b4, Tff7b72nil
Tb4b4b4}

T8b949e// parses a basic value, stopping when the breaker
T8b949e// rune is encountered
Tff7b72func Tb4b4b4(Te6edf3p Tff7b72*Te6edf3ParserTb4b4b4) Te6edf3parseBasicValueTb4b4b4(Te6edf3breaker Tffa657runeTb4b4b4) Tb4b4b4(Tffa657stringTb4b4b4, Tffa657errorTb4b4b4) Tb4b4b4{
Tff7b72var Te6edf3strBuildUp Tff7b72= Ta5d6ff""

Tff7b72for Tb4b4b4{
Te6edf3rTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3CurrentCharacterTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
T8b949e// EOF here is fine if we got some string
Tff7b72if Te6edf3errorsTb4b4b4.Te6edf3IsTb4b4b4(Te6edf3eTb4b4b4, Te6edf3ioTb4b4b4.Te6edf3EOFTb4b4b4) Tff7b72&& Tffa657lenTb4b4b4(Te6edf3strBuildUpTb4b4b4) Tff7b72> T79c0ff0 Tb4b4b4{
Tff7b72break
Tb4b4b4}
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tffa657stringTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4}

T8b949e// newline is immediate end AND we consume
Tff7b72if Te6edf3r Tff7b72== Ta5d6ff'\n' Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tff7b72break
Tb4b4b4}

T8b949e// whitespace
Tff7b72if Te6edf3r Tff7b72== Ta5d6ff' ' Tff7b72|| Te6edf3r Tff7b72== Ta5d6ff'\t' Tb4b4b4{
Tff7b72if Tffa657lenTb4b4b4(Te6edf3strBuildUpTb4b4b4) Tff7b72== T79c0ff0 Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tff7b72continue
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tff7b72break
Tb4b4b4}
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3r Tff7b72== Te6edf3breaker Tb4b4b4{
T8b949e// stop at breaker (and DON'T move cursor)
Tff7b72break
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3r Tff7b72== Ta5d6ff'"' Tb4b4b4{
Tff7b72if Te6edf3strOutTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3parseStringEnclosedValueTb4b4b4(Tb4b4b4)Tb4b4b4; Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tffa657stringTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3DebugTb4b4b4(Ta5d6ff"Obtained string '%s'"Tb4b4b4, Te6edf3strOutTb4b4b4)
Tff7b72return Te6edf3strOutTb4b4b4, Tff7b72nil
Tb4b4b4}
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3strBuildUp Tff7b72+= Tffa657stringTb4b4b4(Te6edf3rTb4b4b4)
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3TraceTb4b4b4(Ta5d6ff"strBuildUp: %s"Tb4b4b4, Te6edf3strBuildUpTb4b4b4)
Tff7b72return Te6edf3strBuildUpTb4b4b4, Tff7b72nil
Tb4b4b4}

T8b949e// parses a section's header
Tff7b72func Tb4b4b4(Te6edf3p Tff7b72*Te6edf3ParserTb4b4b4) Te6edf3parseSection_headerTb4b4b4(Tb4b4b4) Tb4b4b4(Tffa657stringTb4b4b4, Tffa657errorTb4b4b4) Tb4b4b4{
Tff7b72var Te6edf3buildUp Tff7b72= Ta5d6ff""

Tff7b72var Te6edf3nameGotten Tffa657bool Tff7b72= Tff7b72false

Tff7b72for Tb4b4b4{
Te6edf3rTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3CurrentCharacterTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
T8b949e// Note, an EOF here would be BAD
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tffa657stringTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4}

Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3DebugTb4b4b4(Ta5d6ff"I am here: %d"Tb4b4b4, Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3PositionTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3DebugTb4b4b4(Ta5d6ff"I am here: '%c'"Tb4b4b4, Te6edf3rTb4b4b4)

T8b949e// ` hello ]`

T8b949e// if we get whitespace
Tff7b72if Te6edf3r Tff7b72== Ta5d6ff' ' Tff7b72|| Te6edf3r Tff7b72== Ta5d6ff'\t' Tb4b4b4{
T8b949e// if we have not built anything up then skip
Tff7b72if Tffa657lenTb4b4b4(Te6edf3buildUpTb4b4b4) Tff7b72== T79c0ff0 Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tff7b72continue
Tb4b4b4} Tff7b72else Tb4b4b4{ T8b949e// if we have build up then set "nameGotten" flag
Te6edf3nameGotten Tff7b72= Tff7b72true
Tb4b4b4}
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3r Tff7b72== Ta5d6ff']' Tb4b4b4{ T8b949e// closing statement
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4) T8b949e// consume the `]`
Tff7b72break
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3r Tff7b72== Ta5d6ff'\n' Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tffa657stringTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3fmtTb4b4b4.Te6edf3ErrorfTb4b4b4(Ta5d6ff"Got unexpected newline whilst parsing section header"Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
T8b949e// add on if we still need name
Tff7b72if Tff7b72!Te6edf3nameGotten Tb4b4b4{

T8b949e// first character cannot be number
Tff7b72if Tffa657lenTb4b4b4(Te6edf3buildUpTb4b4b4) Tff7b72== T79c0ff0 Tff7b72&& Te6edf3stringsTb4b4b4.Te6edf3IsNumericTb4b4b4(Te6edf3rTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tffa657stringTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3fmtTb4b4b4.Te6edf3ErrorfTb4b4b4(Ta5d6ff"First character of section name cannot be a number, but got '%c'"Tb4b4b4, Te6edf3rTb4b4b4)
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3stringsTb4b4b4.Te6edf3IsAlphaNumericTb4b4b4(Te6edf3rTb4b4b4) Tff7b72|| Te6edf3r Tff7b72== Ta5d6ff'_' Tb4b4b4{ T8b949e// only allow alpha-numeric and underscores
Te6edf3buildUp Tff7b72+= Tffa657stringTb4b4b4(Te6edf3rTb4b4b4)
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tffa657stringTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3fmtTb4b4b4.Te6edf3ErrorfTb4b4b4(Ta5d6ff"Section name can only contain alpha-numeric characters and underscores, but got '%c'"Tb4b4b4, Te6edf3rTb4b4b4)
Tb4b4b4}

Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tffa657stringTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3fmtTb4b4b4.Te6edf3ErrorfTb4b4b4(Ta5d6ff"Expected ] but got more characters"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3TraceTb4b4b4(Ta5d6ff"Parsed section name '%s'"Tb4b4b4, Te6edf3buildUpTb4b4b4)
Tff7b72return Te6edf3buildUpTb4b4b4, Tff7b72nil
Tb4b4b4}

T8b949e// parses a comment
Tff7b72func Tb4b4b4(Te6edf3p Tff7b72*Te6edf3ParserTb4b4b4) Te6edf3parseCommentTb4b4b4(Tb4b4b4) Tb4b4b4(Tffa657stringTb4b4b4, Tffa657errorTb4b4b4) Tb4b4b4{
T8b949e// continue to read until we get a new line
Tff7b72var Te6edf3comment Tffa657string
Tff7b72for Tb4b4b4{
Te6edf3rTb4b4b4, Te6edf3e Tff7b72:= Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3CurrentCharacterTb4b4b4(Tb4b4b4)
T8b949e// EOF is allowed here (we don't care how 'big'
T8b949e// the comment is - it could be zero characters
T8b949e// for all we care)
Tff7b72if Te6edf3errorsTb4b4b4.Te6edf3IsTb4b4b4(Te6edf3eTb4b4b4, Te6edf3ioTb4b4b4.Te6edf3EOFTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3commentTb4b4b4, Tff7b72nil
Tb4b4b4} Tff7b72else Tff7b72if Te6edf3e Tff7b72!= Tff7b72nil Tb4b4b4{
Tff7b72return Te6edf3typesTb4b4b4.Te6edf3ZeroTb4b4b4[Tffa657stringTb4b4b4]Tb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3e
Tb4b4b4}

T8b949e// chomp beginning white space
Tff7b72if Tb4b4b4(Te6edf3r Tff7b72== Ta5d6ff' ' Tff7b72|| Te6edf3r Tff7b72== Ta5d6ff'\t'Tb4b4b4) Tff7b72&& Tffa657lenTb4b4b4(Te6edf3commentTb4b4b4) Tff7b72== T79c0ff0 Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tff7b72continue
Tb4b4b4}

Tff7b72if Te6edf3r Tff7b72== Ta5d6ff'\n' Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4) T8b949e// consume so caller does not have to process it

Te6edf3comment Tff7b72= Te6edf3gostringsTb4b4b4.Te6edf3TrimRightTb4b4b4(Te6edf3commentTb4b4b4, Ta5d6ff" "Tb4b4b4)
Te6edf3pTb4b4b4.Te6edf3logTb4b4b4.Te6edf3TraceTb4b4b4(Ta5d6ff"Parsed comment '%v'"Tb4b4b4, Te6edf3commentTb4b4b4)
Tff7b72return Te6edf3commentTb4b4b4, Tff7b72nil
Tb4b4b4} Tff7b72else Tb4b4b4{ T8b949e// build up everything else
Te6edf3comment Tff7b72+= Tffa657stringTb4b4b4(Te6edf3rTb4b4b4)
Te6edf3pTb4b4b4.Te6edf3cTb4b4b4.Te6edf3NextTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.15s